package parser;

import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.BufferedReader;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import primitive.Article;

public class FileParser {

	private String filename;
	private String current_line;	// Current line read from file
	private String article_buffer;	// Buffer using while article is reading from file
	
	private List<Article> articles_list = new ArrayList<>();
	
	public void run(String filename) {
		System.out.println("Parsering has been started, input file: " + filename);
		
		this.filename = filename;
		
		
		// Let's open a file, which is quite complicated in java... ;/
		try {
			FileInputStream fstream = new FileInputStream(filename);
			DataInputStream in = new DataInputStream(fstream);
			BufferedReader br = new BufferedReader(new InputStreamReader(in));
			
			boolean is_buffer_filling = false;
			Article pure_article;
			
			// Now application can read a file line by line
			while ((current_line = br.readLine()) != null) {
				
				// Let's check that current line has a begin of article
				if (current_line.indexOf("<REUTERS TOPICS") != -1) {
					is_buffer_filling = true;
				}
				
				// Put data to buffer
				article_buffer += current_line + " ";
				
				// Let's check that current line has a end of article
				if (current_line.indexOf("</REUTERS>") != -1) {
					is_buffer_filling = false;
					article_buffer += current_line + " ";
					
					// Call method which is responsible to extract all important information
					//   from article buffer and return pure object with one article :)
					pure_article = article_extractor(article_buffer);
					
					// And finally append pure, extracted article do articles list.
					articles_list.add(pure_article);
					//pure_article.show();
					
					// Clear article buffer
					article_buffer = "";
				}
			}
			
		} catch (Exception e) {
			// This is misery in this language...
		}
		
	}
	
	public Article article_extractor(String article_buffer) {
		Article article = new Article();
		
		// Get DATE
		if (article_buffer.indexOf("<DATE>") == -1) {
			article.setDate("");
		} else {
			article.setDate(article_buffer.substring(article_buffer.indexOf("<DATE>") + 6, article_buffer.indexOf("</DATE>")));
		}
		
		// Get TOPICS
		if (article_buffer.indexOf("<TOPICS>") == -1) {
			article.setTopics("");
		} else {
			article.setTopics(article_buffer.substring(article_buffer.indexOf("<TOPICS>") + 8, article_buffer.indexOf("</TOPICS>")));
		}
		
		// Get PLACES
		if (article_buffer.indexOf("<PLACES>") == -1) {
			article.setPlaces("");
		} else {
			article.setPlaces(article_buffer.substring(article_buffer.indexOf("<PLACES>") + 8, article_buffer.indexOf("</PLACES>")));
		}
		
		// Get PEOPLE
		if (article_buffer.indexOf("<PEOPLE>") == -1) {
			article.setPeople("");
		} else {
			article.setPeople(article_buffer.substring(article_buffer.indexOf("<PEOPLE>") + 8, article_buffer.indexOf("</PEOPLE>")));
		}
		
		// Get ORGS
		if (article_buffer.indexOf("<ORGS>") == -1) {
			article.setOrgs("");
		} else {
			article.setOrgs(article_buffer.substring(article_buffer.indexOf("<ORGS>") + 6, article_buffer.indexOf("</ORGS>")));
		}
		
		// Get EXCHANGES
		if (article_buffer.indexOf("<EXCHANGES>") == -1) {
			article.setExchanges("");
		} else {
			article.setExchanges(article_buffer.substring(article_buffer.indexOf("<EXCHANGES>") + 11, article_buffer.indexOf("</EXCHANGES>")));
		}
		
		// Get COMPANIES
		if (article_buffer.indexOf("<COMPANIES>") == -1) {
			article.setCompanies("");
		} else {
			article.setCompanies(article_buffer.substring(article_buffer.indexOf("<COMPANIES>") + 11, article_buffer.indexOf("</COMPANIES>")));
		}
		
		// Get UNKNOWN
		if (article_buffer.indexOf("<UNKNOWN>") == -1) {
			article.setUnknown("");
		} else {
			article.setUnknown(article_buffer.substring(article_buffer.indexOf("<UNKNOWN>") + 9, article_buffer.indexOf("</UNKNOWN>")));
		}
		
		// Get TITLE
		if (article_buffer.indexOf("<TITLE>") == -1) {
			article.setTitle("");
		} else {
			article.setTitle(article_buffer.substring(article_buffer.indexOf("<TITLE>") + 7, article_buffer.indexOf("</TITLE>")));
		}
		
		// Get DATELINE
		if (article_buffer.indexOf("<DATELINE>") == -1) {
			article.setDateline("");
		} else {
			article.setDateline(article_buffer.substring(article_buffer.indexOf("<DATELINE>") + 10, article_buffer.indexOf("</DATELINE>")));
		}
		
		// Get BODY
		if (article_buffer.indexOf("<BODY>") == -1) {
			article.setBody("");
		} else {
			article.setBody(article_buffer.substring(article_buffer.indexOf("<BODY>") + 6, article_buffer.indexOf("</BODY>")));
		}
		
		return article;
	}
	
	public int size() {
		return articles_list.size();
	}
	
	public void drop_useless_articles() {
		//
		/*
		for (Article article : articles_list) {
			if (keep_article_1(article) == false) {
				// Remove it!
				articles_list.remove(article);
			}
		}*/
		
		for (int i = articles_list.size() - 1; i >= 0; i--) {
			if (keep_article_2(articles_list.get(i)) == false) {		// change!
				articles_list.remove(i);
			}
		}
	}
	
	public void save_articles(String filename, List<String> labels, int start, int end) {
		int c = 0;
		try {
			FileWriter fstream = new FileWriter(filename);
			BufferedWriter out = new BufferedWriter(fstream);
			
			for (Article article : articles_list) {
				
				c++;
				
				if (c >= start && c <= end) {
				
					out.write("<ARTICLE>\n");
					
					if (labels.indexOf("date") != -1) {
						out.write("<DATE>" + article.getDate() + "</DATE>\n");
					}
					
					if (labels.indexOf("topics") != -1) {
						out.write("<TOPICS>" + article.getTopics() + "</TOPICS>\n");
					}
					
					if (labels.indexOf("places") != -1) {
						out.write("<PLACES>" + article.getPlaces() + "</PLACES>\n");
					}
					
					if (labels.indexOf("people") != -1) {
						out.write("<PEOPLE>" + article.getPeople() + "</PEOPLE>\n");
					}
					
					if (labels.indexOf("orgs") != -1) {
						out.write("<ORGS>" + article.getOrgs() + "</ORGS>\n");
					}
					
					if (labels.indexOf("exchanges") != -1) {
						out.write("<EXCHANGES>" + article.getExchanges() + "</EXCHANGES>\n");
					}
					
					if (labels.indexOf("companies") != -1) {
						out.write("<COMPANIES>" + article.getCompanies() + "</COMPANIES>\n");
					}
					
					if (labels.indexOf("unknown") != -1) {
						out.write("<UNKNOWN>" + article.getUnknown() + "</UNKNOWN>\n");
					}
					
					if (labels.indexOf("title") != -1) {
						out.write("<TITLE>" + article.getTitle() + "</TITLE>\n");
					}
					
					if (labels.indexOf("dateline") != -1) {
						out.write("<DATELINE>" + article.getDateline() + "</DATELINE>\n");
					}
					
					if (labels.indexOf("body") != -1) {
						out.write("<BODY>" + article.getBody() + "</BODY>\n");
					}
					out.write("</ARTICLE>\n\n");
				
				}
			}
			
			out.close();			
		} catch (Exception e) {
			//
		}
	}
	
	
	// Methods used to decide that article is usefull or useless.
	public boolean keep_article_1(Article article) {
		// Klasyfikacja tekstów, które w powyższym zestawie danych w kategorii places posiadają
		// etykiety: west-germany, usa, france, uk, canada, japan i są to ich jedyne etykiety w tej
		// kategorii.
		
		ArrayList<String> interesting_places = new ArrayList<>();
		interesting_places.add("west-germany");
		interesting_places.add("usa");
		interesting_places.add("france");
		interesting_places.add("uk");
		interesting_places.add("canada");
		interesting_places.add("japan");
		
		if (article.getPlaces().contains("<D>")) {
			if (article.getPlaces().indexOf("<D>") == article.getPlaces().lastIndexOf("<D>")) {
				// There is only one place in this article
				//  let's check that place is interesting for us
				if (interesting_places.contains(
						article.getPlaces().substring(
								article.getPlaces().indexOf("<D>") + 3,
								article.getPlaces().indexOf("</D>"))))
					return true;
			}
		}

		return false;
	}
	
	public boolean keep_article_2_frame(Article article) {
		// Klasyfikacja tekstów w ramach innej kategorii niż opisana powyżej z minimum dwiema
		// etykietami.
		
		return false;
	}
	
	public boolean keep_article_2(Article article) {
		// Klasyfikacja tekstów, które w powyższym zestawie danych w kategorii places posiadają
		// etykiety: west-germany, usa, france, uk, canada, japan i są to ich jedyne etykiety w tej
		// kategorii.
		
		ArrayList<String> interesting_places = new ArrayList<>();
		interesting_places.add("sumita");
		interesting_places.add("maxwell");
		interesting_places.add("young");
		interesting_places.add("thatcher");
		interesting_places.add("miyazawa");
		
		if (article.getPeople().contains("<D>")) {
			if (article.getPeople().indexOf("<D>") == article.getPeople().lastIndexOf("<D>")) {
				// There is only one place in this article
				//  let's check that place is interesting for us
				if (interesting_places.contains(
						article.getPeople().substring(
								article.getPeople().indexOf("<D>") + 3,
								article.getPeople().indexOf("</D>"))))
					return true;
			}
		}

		return false;
	}
	
}
